home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr05 / ppp25.zip / PPP.DOC next >
Text File  |  1994-11-14  |  77KB  |  2,087 lines

  1.  
  2.                           POV-Ray and
  3.                           Polyray
  4.                           Preprocessor   Version 2.5
  5.  
  6.  
  7.                           By John R. Wind
  8.                           November 1994
  9.                           Compuserve: 72604,1344
  10.                           Internet: JOHNWIND@DELPHI.COM
  11.  
  12.   Introduction:
  13.  
  14.     It started when I saw several utilities for POV that would do simple
  15.   things like a rectangular array of objects, or a circular array of
  16.   objects.  I thought that it would be nice if POV or Polyray had a
  17.   command like a For-Next loop to do things like this.  After working on
  18.   this program (referred to as P-cubed), I see that if the raytracer had
  19.   commands like that, the only indication you would have if there was
  20.   some error in your source file is that visually the scene might not
  21.   look right.  It would be better to see a listing of the the kind of
  22.   objects that a command like that produced before it was rendered.  The
  23.   answer is a preprocessor that can parse a file with these additional
  24.   commands embedded along with raytracer statements and output a normal
  25.   raytracer source file that you can render.  Well, I fired up QBASIC and
  26.   hacked away.  Why QBASIC?  Because it was there, and I understand BASIC
  27.   better than C language.  Plus, I could always compile the results with
  28.   Microsoft QuickBasic 4.5 for a stand-alone command line executable.  I
  29.   know that C language may produce a faster executable program, but when
  30.   you consider that raytracing may take several minutes even on a fast
  31.   machine, 1 minute to execute a preprocessor is a drop in the bucket.  As
  32.   time went on, one feature led to another, and the result grew from humble
  33.   beginnings into a robust language.
  34.   Current features include:
  35.  
  36.         Floating Point, and Vector variables
  37.         Extensive Vector and Scalar Math Functions.
  38.         Loops (DO, UNTIL)
  39.         Conditional Statements (IF, ELSE)
  40.         Recursive Subprograms
  41.         Local and World Axis Calculations
  42.         Can do L-system objects similar to LPARSER
  43.         Multiple Input and Output files
  44.         Will work with POV or Polyray
  45.  
  46.  
  47.   Usage:
  48.  
  49.         PPP Sourcefilename[.ppp] [Outputfilename]
  50.  
  51.         The Output file is optional.  If one is not specified then the
  52.         default output will be sent to a temporary default output file
  53.         "temp.$$$" which is deleted at the end of processing.  This
  54.         allows one to specify output file(s) from within the source file
  55.         if desired.
  56.  
  57.   Conventions:  Some things to take note of
  58.  
  59.     * P-cubed is designed as a preprocessor.  It passes raytracer
  60.   statements in the input file straight through to the output file.
  61.   That is, an ordinary POV or Polyray input file will not be changed by
  62.   running it through P-cubed.  P-cubed will take a POV or Polyray input
  63.   file with P-cubed commands added and use those commands to generate a
  64.   modified output file in POV or Polyray format that can be rendered.
  65.  
  66.     * P-cubed is not limited to POV or Polyray format, it has just been
  67.   designed not to let any P-cubed commands be confused with POV or
  68.   Polyray statements, and it outputs vectors enclosed in <> brackets
  69.   that are required by POV and Polyray (i.e. <1, 2, 3>).  It is also
  70.   capable of generating Raw triangle files, Batch files, Text files in
  71.   general, use your imagination.
  72.  
  73.     * Lines that do not contain a P-cubed command as the first word are
  74.   passed on to the output file as is.  The only exception is when a line
  75.   contains embedded value references.  Then the line is passed on to
  76.   the output file with the value(s) inserted in place of the reference(s).
  77.   This is much the same as DOS batch files make use of environment variables.
  78.  
  79.     * All P-cubed commands begin with a # symbol i.e. #var, #print,
  80.   but raytracer statements that already begin with a # symbol like
  81.   "#include" and "#declare" will be passed on to the output file and not
  82.   confused with a P-cubed command.
  83.  
  84.     * Blank lines will be passed on to the output file.  If you need
  85.   some blank lines in the source file, but don't want them to show up in
  86.   the output file, then put a single # symbol at the beginning of a blank
  87.   line in the source file and that line will not be passed on to the
  88.   output file.
  89.  
  90.     * P-cubed does very little syntax checking.  I've added a few
  91.   error messages for obvious errors, but I didn't want to waste all my
  92.   time playing "what if".  If you don't get an error message, but the
  93.   results just aren't coming out right, output some of the variables at
  94.   intermediate points in the program to let you trace what is happening
  95.   (or not happening).  This will help you locate the error.
  96.  
  97.     * I've tried to make P-cubed syntax free format and as tolerant as
  98.   possible of minor syntax variations.
  99.   Example: "#let x = 2 2 +" will parse just the same as "#let x=2 2 +".
  100.  
  101.     * Variables can be Floating point numbers or Vectors and the math
  102.   functions don't confirm that you are using mathematically well defined
  103.   combinations.  Example: You can multiply a vector by a vector.
  104.   This is not defined mathematically, and P-cubed will produce equally
  105.   meaningless results, but it will do it.
  106.  
  107.     * All numbers are kept track of internally as double-precision 16
  108.   digit floating point values, but are rounded to a user specified number
  109.   of digits when they are output to a file.  This helps offset some
  110.   problems with the precision of floating point numbers and raytracers
  111.   have problems with double-precision numbers in QBASIC exponential
  112.   format i.e. 1D-6.
  113.  
  114.  
  115.   Now, on to programming.
  116.  
  117.  
  118.   Variables:
  119.  
  120.     Variables may represent Floating point, or Vector values.  P-cubed
  121.   keeps track of the variable type for math operations and output
  122.   formatting.  All variables must begin with an alphabetic character
  123.   (a-z), and should not be the same as one of the built-in function
  124.   names.  Variables may be up 12 characters long and are case insensitive.
  125.   Variables are declared by using the #var command.
  126.   The syntax for the #var command is:
  127.  
  128.        #var name1[, name2, name3, ...]
  129.        Examples:  #var john
  130.                   #var a, b, cat, dog
  131.  
  132.   The #var command will define the variable(s) and initialize the
  133.   value(s) of the variable(s) to a Floating point 0.
  134.  
  135.   Variables may be defined multiple times.
  136.  
  137.      Example:
  138.          -->  #var a, b, c, b, d, [b:6]
  139.  
  140.   In the example we defined a, b, c, then defined b again, then
  141.   defined d, and defined b six more times.  This is kind of a poor man's
  142.   one-dimensional array.  The specification "[varname:number]" defines
  143.   a quantity of variables of name=varname and amount=number.  The same
  144.   specifcation "[varname:index]" also lets us refer to previous values
  145.   of a variable that has been defined multiple times.  When we refer to
  146.   these multiple variables, "b" would refer to the very latest definition
  147.   of b (in our case the last element of the [b:6] array).  Likewise, [b:0]
  148.   also refers to the very latest definition of the "b" variable.  [b:1]
  149.   would refer to the next-to-the-last definition of "b".  [b:5] would refer
  150.   to the first instance of "b" right after the definition of "d", [b:6]
  151.   would refer to the definition of "b" that is between c and d, and [b:7]
  152.   would refer to the first definition of "b" right after "a".
  153.  
  154.  
  155.   Outputting a line to the output file:
  156.  
  157.     An output line is simply any line that does not begin with a P-cubed
  158.   command.  Even blank lines will be sent to the output file.  You can
  159.   embed data in an output line by enclosing it in percent signs.
  160.  
  161.          Example: (Assuming variable a = 3.45 and b={3, 4, 5} )
  162.                   sphere { %b%, %a% }
  163.          Would output:
  164.                   sphere { < 3, 4, 5 >, 3.45 }
  165.  
  166.   In our example, "a" was a variable of value 3.45 and "b" was a variable
  167.   that had the vector value {3, 4, 5}.  We put the specification %a% in
  168.   our output line where we wanted the value of "a" to be and %b% where we
  169.   wanted the value of "b" to be.  Note that vectors come out enclosed in
  170.   < > brackets consistent with POV and Polyray vector definitions.  If a
  171.   % sign is required in the output, then use "%%" in the input file to
  172.   specify a percent sign.
  173.  
  174.          Example:
  175.                  I am 100%% ready.
  176.          Would output as:
  177.                  I am 100% ready.
  178.  
  179.   Anything that evaluates as a number or a vector may be put in an
  180.   output line embedded between % signs.  This includes a number, a
  181.   vector, a variable, and an evaluated expression.
  182.  
  183.  
  184.   Appending to an Output line:
  185.  
  186.     To append to a previous output line, just begin the next line with
  187.   "#+" and everything immediately after the "#+" will be added to the
  188.   previous output line.
  189.  
  190.          Example:
  191.                  abcdefg
  192.                  #+hijklmnop
  193.          Would output as:
  194.                  abcdefghijklmnop
  195.  
  196.  
  197.   Comments:
  198.  
  199.     To add a comment to the source file only, so that it does not show
  200.   up in the output file, Begin a line with the # symbol and then at
  201.   least one space.
  202.  
  203.          Example:
  204.                  # This is a comment
  205.                  #     This is a comment also
  206.                  #This is not a comment and will be in the output file
  207.  
  208.   The first two lines would not show up in the output file, but the
  209.   third one would because there was not at least one space between the #
  210.   symbol and the first word.  Completely blank lines will be passed on
  211.   to the output file, so, if you want to add some space to your source
  212.   file and not the output, remember to Put a # symbol at the beginning
  213.   of a blank line and it will not show up in the output.
  214.  
  215.  
  216.   The #print command:
  217.  
  218.     The #print command serves to send output to the screen only.
  219.   Nothing that is on the same line with the print command is sent to the
  220.   output file, just to the screen.  The syntax is:
  221.  
  222.          #print line_output_to_screen
  223.  
  224.          Example:
  225.                  #var a, b
  226.                  #let a = 1
  227.                  #let b = { 3, 4, 5 }
  228.                  #print a=%a%, and b=%b%
  229.           Would print to the screen only:
  230.                  a= 1, and b= < 3, 4, 5 >
  231.  
  232.   This same line without the #print command in front would be sent to
  233.   the output file.
  234.  
  235.  
  236.   The #open command:
  237.  
  238.     The #open command lets you open a file for input or output.  Any
  239.   number of files may be open at one time up to the limit set by the
  240.   FILES statement in your CONFIG.SYS file.
  241.   The syntax is:
  242.  
  243.          #open in|out variable filename
  244.  
  245.          Example:
  246.                  #var inpnum, outnum
  247.                  #open in inpnum infile.ppp
  248.                  #open out outnum outfile.pov
  249.  
  250.   The example would open a file called "infile.ppp" for input and it
  251.   will be referred to by the file number in variable "inpnum".  The
  252.   example also opens a file called "outfile.pov" for output and it will
  253.   be referred to by the file number in variable "outnum".  Values may
  254.   be embedded in the filname in order to add numbers to a filename.
  255.   These numbers are truncated to a positive integer value.
  256.  
  257.          Example:
  258.                  #var outnum, num
  259.                  #let num = 99.1
  260.                  #open out outnum file%num%.ppp
  261.  
  262.   The example would open a file called "file99.ppp" for output and it
  263.   will be referred to by the file number in variable "outnum".
  264.  
  265.  
  266.   The #input command:
  267.  
  268.     The #input command directs P-cubed to get it's input from another
  269.   source file that you have opened.  The new source file is parsed until
  270.   it's end is reached, then P-cubed returns to parsing the previous
  271.   source file.  You may "#input" the same source file several times if
  272.   desired (useful for multiple copies of an object in another source
  273.   file).  The syntax is:
  274.  
  275.          #input var
  276.          where the variable contains the file number of an open file.
  277.  
  278.          Example:
  279.                  #var inpnum
  280.                  #open in inpnum myfile.ppp
  281.                  #input inpnum
  282.  
  283.   The example would open the file "myfile.ppp" for input and then parse
  284.   the commands in that file.  When the end of "myfile.ppp" is reached,
  285.   P-cubed will return to parsing the next statement of the previous
  286.   input file.
  287.  
  288.  
  289.   The #output command:
  290.  
  291.     The #output command directs P-cubed to send it's output to another
  292.   output file that you have opened.  The #output command can also be used
  293.   to send P-cubed output back to the original default output file.
  294.   The syntax is:
  295.  
  296.          #output [variable]
  297.          The optional variable contains the file number of an open file.
  298.  
  299.          Example:
  300.                  #var outnum
  301.                  #open out outnum myfile.pov
  302.                  #output outnum
  303.                  line sent to myfile.pov
  304.                  #output
  305.                  line sent to default output file
  306.  
  307.   The example would open a file named "myfile.pov" for output and then
  308.   tells P-cubed to send all output to that file.  After one line is sent
  309.   to "myfile.pov", the second #output command tells P-cubed to send all
  310.   output to the default output file again.
  311.  
  312.  
  313.   The #close command:
  314.  
  315.     The #close command closes a file that you have opened for input or
  316.   output.  This is usually not necessary as P-cubed closes all files
  317.   when it is finished executing, but you may run into situations when
  318.   there may be too many files open at once and you have to close a few.
  319.   The syntax is:
  320.  
  321.          #close variable
  322.          where the variable contains the file number of an open file.
  323.  
  324.  
  325.   The #let command:
  326.  
  327.     The #let command serves to assign a value to a variable.  This value
  328.   could be a literal floating point number, a literal vector, the value of
  329.   another variable, or an evaluated mathematical expression.
  330.   The syntax for a #let command is:
  331.  
  332.               #let variable = value
  333.               Examples:
  334.                       #let a = 1
  335.                       #let b = { 1, 2, 3 }
  336.                       #let d = a
  337.                       #let [b:2] = 5
  338.                       #let e = a c +
  339.                       #let f = e rand
  340.  
  341.   Let's start with the simplest case:
  342.                        #let var = value
  343.  
  344.   A value may be a literal floating point number i.e. 3.1415926
  345.   A value may also be a literal vector i.e. { 1, 2, 3.1415926 }.
  346.   Vectors are three values sepatated by commas and enclosed in { }
  347.   brackets.
  348.  
  349.     Example:
  350.               #let a = 4.25                <-- "a" is a number
  351.               #let b = {1.2, 2.3, 3.4}     <-- "b" is a vector
  352.  
  353.   Values may also be represented by a variable reference.
  354.  
  355.     Example:
  356.               #let a = b
  357.     means put the value of variable "b" in variable "a"
  358.  
  359.   Now notice that a literal vector contains three values, which may also
  360.   be represented by a variable reference.
  361.     Example:
  362.               #let b = 1
  363.               #let c = { b, 2, 3 }
  364.     means that the value of variable "c" is the vector { 1, 2, 3 }
  365.  
  366.   A value may also be preceeded by a "-" to negate it
  367.     Example:
  368.               #let b = -1
  369.               #let c = 2
  370.               #let d = { b, -c, 3 }
  371.     means that the value of variable "d" is the vector { -1, -2, 3 }
  372.  
  373.   Now let's try some math.
  374.  
  375.     First, all math is done in "reverse polish notation", referred to as
  376.     "RPN".  That is, we switch from having the math operator between the
  377.     two arguments (infix) to putting it at the end (postfix).
  378.  
  379.          Example:
  380.                  #let a = 2 + 2               <-- Algebraic Notation
  381.          Would be written:
  382.                  #let a = 2 2 +               <-- RPN
  383.  
  384.     This may seem like a trivial change, but it makes it much easier for
  385.     the program to understand complex expressions.
  386.  
  387.          Example:
  388.                  #let a = (4 + 3) * (5 + 6)   <-- Algebraic Notation
  389.          Would be written as:
  390.                  #let a = 4 3 + 5 6 + *       <-- RPN
  391.  
  392.     In algebraic notation, the program would have to keep track of
  393.     precedence of operators.  That is why we had to add the parentheses,
  394.     so that the additions were performed before the multiplication.
  395.     Reverse polish notation (RPN) gets away from this by simply
  396.     evaluating the expression from left to right.  Reading from left to
  397.     right, the RPN sequence of the last example goes like this:
  398.  
  399.              Step: Reads:    Function:                     Stack:
  400.              1.    4         Push 4 onto the stack         4 <-
  401.  
  402.              2.    3         Push 3 onto the stack         4 3 <-
  403.  
  404.              3.    +         Remove the top two numbers
  405.                              from the stack (4 and 3)
  406.                              and add them, and put the
  407.                              answer on the stack.          7 <-
  408.  
  409.              5.    5         Push 5 onto the stack         7 5 <-
  410.  
  411.              6.    6         Push 6 onto the stack         7 5 6 <-
  412.  
  413.              7.    +         Remove the top two numbers
  414.                              from the stack (5 and 6)
  415.                              and add them, and put the
  416.                              answer on the stack.          7 11 <-
  417.  
  418.              8.    *         Remove the top two numbers
  419.                              from the stack (the answers
  420.                              from step 3 and step 7) and
  421.                              multiply them and put
  422.                              the answer on the stack       77 <-
  423.  
  424.              9.              The answer is removed from    <-
  425.                              the stack and put in the
  426.                              variable "a"
  427.  
  428.   The stack is a temporary storage place for numbers and vectors,
  429.   sometimes called a last-in-first-out stack because the last number you
  430.   put in is the first number you get out.  All math functions just get
  431.   numbers from the top of the stack, perform some mathematical operation
  432.   on them, and then put the answer on the stack.  The #let command
  433.   evaluates the expression, gets what is left on top the stack, and puts
  434.   it in the variable you specify.  So "#let a = 4" is evaluating an
  435.   expression that puts 4 on top of the stack, and then puts the number on
  436.   top of the stack in variable "a".  Actually, the correct description of
  437.   a #let command is:
  438.  
  439.          #let variable = expression
  440.  
  441.   P-cubed has many RPN math functions and they all make use of the
  442.   stack, so in order to describe the RPN math functions I will include a
  443.   stack effect description.
  444.  
  445.          Example:
  446.                  (n1 n2 -> n3)
  447.  
  448.   Means that the function will expect values n1 and n2 to be on
  449.   top of the stack and it will remove them, perform some function on
  450.   them, and place the answer n3 on top of the stack.  Any value placed
  451.   in an RPN expression is pushed onto the stack automatically, so if the
  452.   function expects two values from the stack, just place those two
  453.   values before the function in the RPN expression.
  454.  
  455.          Example:
  456.                  2 3 +
  457.          Would place the values 2 and 3 on the stack, perform the
  458.          addition function, and leave the value 5 on top of the stack.
  459.  
  460.   Here are RPN Scalar and Vector math functions.
  461.  
  462.     Function:  Stack:           Description:
  463.  
  464.         +      (n1 n2 -> n3)    Adds n1 and n2
  465.  
  466.         +=     (v1 n1 ->   )    Adds n1 to variable v1 and puts the
  467.                                 answer directly in variable v1.
  468.                                 No value is left on the stack.
  469.  
  470.         ++     (v1 ->      )    Adds 1 to variable v1 and puts the
  471.                                 answer directly in variable v1.
  472.                                 No value is left on the stack
  473.  
  474.         -      (n1 n2 -> n3)    Subtracts n2 from n1
  475.  
  476.         -=     (v1 n1 ->   )    Subtracts n1 from variable v1 and puts
  477.                                 the answer directly in variable v1.
  478.                                 No value is left in the stack.
  479.  
  480.         --     (v1 ->      )    Subtracts 1 from variable v1 and puts
  481.                                 the answer directly in variable v1.
  482.                                 No value is left on the stack.
  483.  
  484.         *      (n1 n2 -> n3)    Multiplies n1 by n2
  485.  
  486.         *=     (v1 n1 ->   )    Multiplies variable v1 by n1 and puts
  487.                                 the answer directly in variable v1.
  488.                                 No value is left on the stack.
  489.  
  490.         /      (n1 n2 -> n3)    Divides n1 by n2
  491.  
  492.         /=     (v1 n1 ->   )    Divides variable v1 by n1 and puts the
  493.                                 answer directly in variable v1.
  494.                                 No value is left on the stack.
  495.  
  496.         ^      (n1 n2 -> n3)    Raises n1 to the n2 power
  497.  
  498.         abs    (n1 -> n2)       Finds the absolute value of n1
  499.  
  500.         sqr    (n1 -> n2)       Finds the Square root of n1
  501.  
  502.         sgn    (n1 -> n2)       -1 if n1 is negative,
  503.                                  0 if n1 is zero
  504.                                  1 if n1 is positive
  505.  
  506.         log    (n1 -> n2)        Natural logarithim of n1
  507.  
  508.         exp    (n1 -> n2)        e to the n1 power
  509.  
  510.         sin    (n1 -> n2)        Sine of n1 (in degrees)
  511.  
  512.         cos    (n1 -> n2)        Cosine of n1 (in degrees)
  513.  
  514.         tan    (n1 -> n2)        Tangent of n1 (in degrees)
  515.  
  516.         atn    (n1 -> n2)        ArcTangent of n1 (answer in degrees)
  517.  
  518.         int    (n1 -> n2)        Largest integer less than or equal to n1
  519.  
  520.         fix    (n1 -> n2)        n1 truncated to an integer value
  521.  
  522.   Now, some RPN vector math
  523.  
  524.         dot    (n1 n2 -> n3)     Dot product of vector n1 and n2
  525.  
  526.         cross  (n1 n2 -> n3)     Cross product of vector n1 and n2
  527.  
  528.         mag    (n1 -> n2)        Magnitude of vector n1
  529.  
  530.         rot    (n1 n2 -> n3)     Vector n1 rotated about the origin by
  531.                                  the x, y, and z degrees in vector n2.
  532.                                  i.e. "{1, 0, 0} {30, 60, 90} rot" would
  533.                                  rotate the vector {1, 0, 0} by 30
  534.                                  degrees about the x-axis, then 60 degrees
  535.                                  about the y-axis, and then 90 degrees
  536.                                  about the z-axis.  A left-handed
  537.                                  coordinate system is used.
  538.  
  539.         turn   (n1 n2 n3 -> n4)  Vector n1 rotated about vector n2 by
  540.                                  n3 degrees.
  541.                                  i.e. "{1, 0, 0} {1, 1, 0} 180 turn" would
  542.                                  rotate the vector {1, 0, 0} by 180 degrees
  543.                                  about vector {1, 1, 0} in a left-handed
  544.                                  direction.
  545.  
  546.         getx   (n1 -> n2)        Gets the x component of vector n1
  547.  
  548.         gety   (n1 -> n2)        Gets the y component of vector n1
  549.  
  550.         getz   (n1 -> n2)        Gets the z component of vector n1
  551.  
  552.         getxyz (vec -> nz ny nx) Decomposes a vector into x, y, and z
  553.                                  components.
  554.  
  555.         vector (nx ny nz -> vec) Takes three components, x, y, and z,
  556.                                  and generates a vector
  557.  
  558.  
  559.   and some misc. functions
  560.  
  561.         rand   (n1 -> n2)        A random number from 0 to n1 if n1 is a
  562.                                  number, or from {0, 0, 0} to {x1, y1, z1}
  563.                                  if n1 is a vector.
  564.  
  565.         noise  (n1 -> n2)        Finds a noise value from 0 to 1 for the
  566.                                  vector coordinate n1.  Coordinates that
  567.                                  are more than one unit distant from
  568.                                  each other will have noise values that
  569.                                  are relatively random with respect to
  570.                                  each other, but coordinates that are
  571.                                  less than 1 unit distant from each
  572.                                  other will have noise values that are
  573.                                  almost the same.  This provides a
  574.                                  smoothly varying random value for all
  575.                                  points in space.
  576.  
  577.         ==     (v1 n1 ->   )     Puts value n1 in variable v1.
  578.                                  No value is left on the stack.
  579.  
  580.         dupe   (n1 -> n1 n1)     Duplicates n1 on top of the stack
  581.  
  582.         swap   (n1 n2 -> n2 n1)  Swaps n1 and n2 in the stack
  583.  
  584.         drop   (n1 ->   )        Drops the number on top of the stack
  585.  
  586.         over   (n1 n2 -> n1 n2 n1)
  587.                                  Duplicates n1 (the next-to-top value)
  588.                                  and puts it on top of the stack.
  589.  
  590.         vstack?  (  -> n1)       Current depth of Value stack
  591.  
  592.         astack?  (  -> n1)       Current depth of Axis stack
  593.  
  594.         level?   (  -> n1)       Current nested and/or recursive subprg
  595.                                  call level.
  596.  
  597.  
  598.   An evaluated expression may be used in place of a value by enclosing
  599.   the expression in parenthesis.  i.e. (2 2 +) may be substituted anywhere
  600.   you would put the value 4.
  601.  
  602.          Example:
  603.                  #let a = { 1, (2 3 *), 9}
  604.          Would set "a" equal to the vector {1, 6, 9}
  605.  
  606.          or:
  607.                  sphere { < 1, 0, 0 >, %(2 5 +)% }
  608.          Would output the line
  609.                  sphere { < 1, 0, 0 >, 7 }
  610.  
  611.   Perhaps, you already have a have a value on top of the stack and would
  612.   like to use it somewhere.  The value on top of the stack may be be
  613.   specified by just "()".
  614.  
  615.          Example: (Assuming the value 4 is on top of the stack)
  616.                  #let a = { 1, 2, () }
  617.          Would set a = { 1, 2, 4 }
  618.  
  619.  
  620.   The #eval command:
  621.  
  622.     The #eval command takes an expression and evaluates it.  This is for
  623.   expressions that either have no effect on the stack, or have an effect
  624.   on the stack that will be made use of later.
  625.  
  626.          Example:
  627.                  #eval {0, 0, 0} 5 {20, 0, 0} 10 connect
  628.          Would find the cone section that would smoothly connect the
  629.          two spheres whose centers and radii are specified and leave
  630.          the answer on top of the stack in the form:
  631.                             rad2 end2 rad1 end1 <-
  632.  
  633.          So that later they may be popped off the stack in the order:
  634.                             end1 rad1 end2 rad2
  635.  
  636.          or, just used in a raytracer cone statement by
  637.                   cone { %()%, %()%, %()%, %()% }
  638.          Where
  639.          () pops   -->   end1  rad1  end2  rad2
  640.  
  641.  
  642.   The #push and #pop commands:
  643.  
  644.     The #push and #pop commands serve to save and recover values on the
  645.   "last in first out" stack.  Their syntax is:
  646.  
  647.          #push value [value2 value3 ...]
  648.          #pop var [var2 var3 ...]
  649.  
  650.          Example:
  651.                  #var a, b
  652.                  #let a = 1
  653.                  #let b = { 3, 4, 5 }
  654.                  #push a b
  655.                  #pop a b
  656.                  #print a=%a%, b=%b%
  657.          Would print:
  658.                  a= < 3, 4, 5 >, b= 1
  659.  
  660.   The example demonstrates a simple use of the #push and #pop commands,
  661.   which swaps the values of two variables.  Note that the values are
  662.   swapped because the value of "b" was the last pushed onto the stack
  663.   and the first value popped off of the stack was put in "a".
  664.  
  665.  
  666.   The #if, #else and #endif commands:
  667.  
  668.     The #if, #else and #endif commands provide a way to process blocks of
  669.   commands only under certain conditions.
  670.   Their syntax is:
  671.  
  672.          #if conditional_expression
  673.            ...
  674.          #else [optional_expression]
  675.            ...
  676.          #endif [optional_expression]
  677.  
  678.   The #else command is optional.  You can have just #if and #endif.
  679.   The conditional_expression after #if is any expression that leaves
  680.   either a zero or non-zero value on top of the stack.  A zero value
  681.   means "false" and the #if section will be skipped and the #else
  682.   section will be processed.  A non-zero value means "true" and the #if
  683.   section will be processed and the #else section skipped.
  684.  
  685.   RPN functions for conditional expressions are:
  686.  
  687.     Function:  Stack:           Description:
  688.  
  689.         <      (n1 n2 -> n3)    n3 is true if n1 is less than n2
  690.  
  691.         >      (n1 n2 -> n3)    n3 is true if n1 is greater than n2
  692.  
  693.         =      (n1 n2 -> n3)    n3 is true if n1 equals n2
  694.  
  695.         <>     (n1 n2 -> n3)    n3 is true if n1 doesn't equal n2
  696.  
  697.         <=     (n1 n2 -> n3)    n3 is true if n1 is less than or equal to n2
  698.  
  699.         >=     (n1 n2 -> n3)    n3 true if n1 is greater than or equal to n2
  700.  
  701.         not    (n1 -> n2)       n2 is false if n1 is true and vice versa.
  702.  
  703.         and    (n1 n2 -> n3)    n3 is true if n1 and n2 are true.
  704.  
  705.         or     (n1 n2 -> n3)    n3 is true if n1 or n2 is true.
  706.  
  707.         xor    (n1 n2 -> n3)    n3 is true if n1 or n2 is true, but not both.
  708.  
  709.     Where "true" means n3 is a non-zero value, as opposed to "false"
  710.     which means that n3 would be zero.
  711.  
  712.   Here is an example:
  713.  
  714.          #if a 2 <
  715.            #print a is less than 2
  716.          #else
  717.            #print a is greater than or equal to 2
  718.          #endif
  719.  
  720.   You may append an optional expression to the #else and #endif commands
  721.   if desired.  This is just for some additional expressions that you
  722.   want to process and is not required.
  723.  
  724.  
  725.   The #do and #until commands:
  726.  
  727.     The #do and #until commands let you add loops to your program.
  728.   The syntax is:
  729.  
  730.          #do [optional_expression]
  731.            ...
  732.            ...
  733.          #until [conditional_expression]
  734.  
  735.   The conditional expression after the #until command is optional and
  736.   will default to the false condition.  That is, just #until by itself
  737.   will continue the loop indefinitely, or at least until a #break
  738.   instruction is encountered (see below).  Otherwise, the loop continues
  739.   if the conditional expression after #until evaluates false, or the
  740.   loop exits if the conditional expression after #until evaluates true.
  741.  
  742.          Example:
  743.                  #do a 1 ==
  744.                    #print a=%a%
  745.                  #until a ++ a 3 >
  746.          Would print:
  747.                  a= 1
  748.                  a= 2
  749.                  a= 3
  750.  
  751.   The expression after #do initialized "a" to 1.  As the loop iterated,
  752.   the #until command incremented "a" and compared it to 3, and finally
  753.   exitted when "a" was greater than 3.
  754.  
  755.  
  756.   The #break command:
  757.  
  758.     The #break command will break out of a loop immediately.
  759.   The syntax is:
  760.  
  761.          #break [conditional_expression]
  762.  
  763.   The conditional expression is optional and will default to the true
  764.   condition.  Otherwise, the program will break out of the loop if the
  765.   conditional expression evaluates true, or the program will skip the
  766.   #break command if the conditional expression evaluates false.
  767.  
  768.          Example:
  769.                  #var a, b
  770.                  #do a 1 ==
  771.                    #break a 2 >
  772.                    #print a=%a%
  773.                    #eval a ++
  774.                  #until
  775.          Would print:
  776.                  a= 1
  777.                  a= 2
  778.  
  779.   The program initialized "a" to be 1 and then started a loop that
  780.   printed "a" and then incremented "a".  The loop would have continued
  781.   forever, but the #break command broke out of the loop when "a" > 2.
  782.  
  783.  
  784.   The #sub, #endsub and #call commands:
  785.  
  786.     The #sub and #endsub commands serve to define subprograms that may
  787.   be called by the #call command.  In fact, a subprogram may be called
  788.   from within itself, allowing for recursive subprograms.
  789.   The command syntax is:
  790.  
  791.          #sub subname
  792.            ...
  793.            ...
  794.            ...
  795.          #endsub [optional_expression]
  796.          #call subname [conditional_expression]
  797.  
  798.   The optional conditional expression after the #call command defaults
  799.   to the true condition.  Otherwise the subprogram will be called if the
  800.   conditional expression evaluates true or the #call command will be
  801.   skipped if the conditional expression evaluates false.
  802.  
  803.   Since the source file is parsed sequentially from beginning to end, I
  804.   suggest that you put your subprogram definitions at the beginning of
  805.   your source file so that they get defined before the first time they
  806.   are called.  No commands within a subprogram definition will be
  807.   executed until the first time that subprogram is called from outside
  808.   that subprogram definition.  This includes the optional expression
  809.   after the #endsub command which will not be evaluated while the
  810.   subprogram is being defined.  It will be evaluated when the the
  811.   subprogram has been called and the end of the subprogram has been
  812.   reached.
  813.  
  814.          Example:
  815.                  #var a
  816.                  #sub print_a
  817.                    #eval a ++
  818.                    a =%a%
  819.                  #endsub
  820.                  first call of print_a
  821.                  #call print_a
  822.                  returned from print_a
  823.          Would output:
  824.                  first call of print_a
  825.                  a = 1
  826.                  returned from print_a
  827.  
  828.   As P-cubed reads through the example, lines 3 and 4 are ignored at
  829.   first because they are inside a subprogram currently being defined.
  830.   Once P-cubed executes the #call command on line 7, then the next line
  831.   to be parsed will be line 3, the first line of the subprogram. Then the
  832.   rest of the lines in the subprogram will be parsed until the subprogram
  833.   reaches it's end and then returns to the line immediately following the
  834.   #call command that called it.
  835.  
  836.   The last example may be modified to demonstrate recursion.
  837.  
  838.          Example:
  839.                  #var a
  840.                  #sub print_a
  841.                    #eval a ++
  842.                      a =%a%
  843.                      #call print_a a 2 <=
  844.                  #endsub
  845.                  first call of print_a
  846.                  #call print_a
  847.                  returned from print_a
  848.          Would output:
  849.                  first call of print_a
  850.                  a = 1
  851.                  a = 2
  852.                  a = 3
  853.                  returned from print_a
  854.  
  855.   The subprogram calls itself recursively until variable "a" equals 3
  856.   and then it returns back through the chain of recursive calls until it
  857.   has returned from the original call that started it all.
  858.  
  859.   The #call command is also available as an RPN function.
  860.  
  861.      Function:    Stack Effect:       Description:
  862.  
  863.      !subname         none            Unconditional call of subprg "subname"
  864.  
  865.      ?subname       (n1 ->  )         Conditional call of subprg "subname"
  866.                                       If n1 is true (non-zero)
  867.  
  868.   So the previous example with recursion could be written:
  869.  
  870.          Example:
  871.                  #var a
  872.                  #sub print_a
  873.                    #eval a ++
  874.                      a =%a%
  875.                      #eval a 2 <= ?print_a
  876.                  #endsub
  877.                  first call of print_a
  878.                  #eval !print_a
  879.                  returned from print_a
  880.          Would output:
  881.                  first call of print_a
  882.                  a = 1
  883.                  a = 2
  884.                  a = 3
  885.                  returned from print_a
  886.  
  887.  
  888.   Variable definitions made within a called subprogram will be removed
  889.   when the called subprogram returns to it's caller.
  890.  
  891.          Example:
  892.                  #var a, b, c, d
  893.                  #let a = 1
  894.                  #let b = 2
  895.                  #sub new_var
  896.                    #var a, b
  897.                    #let a = 3
  898.                    #let b = 4
  899.                    #print inside sub a =%a%, b =%b%
  900.                  #endsub
  901.                  #print before sub a =%a%, b =%b%
  902.                  #call new_var
  903.                  #print after sub a =%a%, b =%b%
  904.          Would output:
  905.                  before sub a = 1, b = 2
  906.                  inside sub a = 3, b = 4
  907.                  after sub a = 1, b = 2
  908.  
  909.   The subprogram makes new definitions of variables "a" and "b" and then
  910.   removes them when it returns to it's caller.  The definitions of
  911.   variables "a" and "b" inside the subprogram could be considered local
  912.   variables in programmers terms, because they are only accessable within
  913.   the subprogram itself.  The variables "c", and "d" could be considered
  914.   global variables because they are not defined within a subprogram and
  915.   are not redefined within any subprogram so they are always the same no
  916.   mattter where you are.  When we are within the subprogram, the values
  917.   of "a" and "b" are set to 3, and 4, but we could access the old values
  918.   of "a" or "b" by using the reference [a:1] or [b:1].
  919.   This is not possible outside the subprogram because the multiple
  920.   definitions of variables "a" and "b" do not exist there.
  921.  
  922.  
  923.   The #digit command:
  924.  
  925.  
  926.     The #digit command directs P-cubed to truncate the integer part of all
  927.   numbers sent to the output file to a specified number of places before
  928.   the decimal point.
  929.   The syntax is:
  930.  
  931.          #digit value
  932.  
  933.          Example:
  934.                  #digit 3
  935.  
  936.   The example would truncate all numbers sent to the output to 3 places
  937.   before the decimal point.  Note that this includes one place reserved
  938.   for the minus sign of a negative number.  If the output has numbers
  939.   with % signs in front, that means that you did not allow enough places
  940.   for the integer part of that number and should increase the value
  941.   after the #digit command.  The Default value is 7 places.
  942.  
  943.   The #digit command is also an RPN function:
  944.  
  945.                           Value
  946.          Function:        Stack:
  947.  
  948.              digit        (n1 ->  )
  949.  
  950.   So the command:
  951.  
  952.          #eval 3 digit
  953.  
  954.   Would perform the function as the example using the #digit command.
  955.   This is handy for changing output format in the middle of an output
  956.   line.
  957.  
  958.          Example:(assuming a=1 and b=2000)
  959.                  a=%(2 digit a)%, and b=%(5 digit b)%
  960.          Would output:
  961.                  a=  1.00000, and b=  2000.00000
  962.  
  963.  
  964.   The #decim command:
  965.  
  966.     The #decim command directs P-cubed to round off the fractional part
  967.   of all numbers sent to the output file to a specified number of digits
  968.   after the decimal point.  The syntax is:
  969.  
  970.          #decim value
  971.  
  972.          Example:
  973.                  #decim 6
  974.  
  975.   The example would round off the fractional part of all numbers sent to
  976.   the output file to six places after the decimal point.  The Default
  977.   value is 5 places.
  978.  
  979.   The #decim command is also an RPN function:
  980.  
  981.                           Value
  982.          Function:        Stack:
  983.  
  984.              decim        (n1 ->  )
  985.  
  986.   So the command:
  987.  
  988.          #eval 3 decim
  989.  
  990.   Would perform the function as the example using the #decim command.
  991.   This is handy for changing output format in the middle of an output
  992.   line.
  993.  
  994.          Example:(assuming a=1.25 and b=2.00005)
  995.                  a=%(2 decim a)%, and b=%(5 decim b)%
  996.          Would output:
  997.                  a=  1.25, and b=  2.00005
  998.  
  999.  
  1000.   The #seed command:
  1001.  
  1002.     The #seed command directs P-cubed to seed the random number
  1003.   generator for the "rand" and "noise" RPN functions.
  1004.   The syntax is:
  1005.  
  1006.          #seed [value]
  1007.          Where the value is optional
  1008.  
  1009.          Example:
  1010.                  #seed 1.2345
  1011.  
  1012.   The value after the #seed command is used to seed the random number
  1013.   generator.  Processing a P-cubed file with the same random number seed
  1014.   will produce the same sequence of random numbers each time.  If the
  1015.   value after the #seed command is omitted, then the random number
  1016.   generator will be seeded by the internal timer, (the number of seconds
  1017.   since midnight) and will produce a different sequence of random numbers
  1018.   each time (assuming you haven't waited EXACTLY 24 hours to try again).
  1019.  
  1020.  
  1021.   The #connect command:
  1022.  
  1023.     The #connect command performs calculations for finding a cone
  1024.   section that will smoothly connect two spheres of different radius.
  1025.   This is useful for generating objects that are a series of connected
  1026.   spheres (a.k.a. "connect-the-dots").
  1027.   The syntax is:
  1028.  
  1029.          #connect center1 radius1 center2 radius2
  1030.  
  1031.          Where center1 and center2 are vector values that
  1032.          are the centers of the spheres you are connecting and
  1033.          radius1 and radius2 are floating point values that are
  1034.          the radii of the spheres that you are connecting.
  1035.  
  1036.          The cone parameters are left on the stack and may be assigned
  1037.          to variables by:
  1038.  
  1039.          #pop end1 radius1 end2 radius2
  1040.  
  1041.          Example:
  1042.                  #connect {0, 0, 0} 4 {0, 0, 15} 10
  1043.                  #pop e1 r1 e2 r2
  1044.                  cone { %e1%, %r1%, %e2%, %r2% }
  1045.  
  1046.   The example connects two spheres of radius 4 and 10.  The parameters
  1047.   for the cone section are left on the stack and are assigned to
  1048.   variables by the #pop command.  The POV cone statement would define a
  1049.   cone section that would smoothly connect the two spheres.
  1050.  
  1051.   An easier method would be to use the RPN connect function
  1052.  
  1053.          Function:      Stack:
  1054.  
  1055.          connect        (cent1 rad1 cent2 rad2 -> rad2 end2 rad1 end1)
  1056.  
  1057.   Like the #connect command, the RPN connect function leaves the answers
  1058.   on the stack, in the correct order so that you may pop them off the
  1059.   top of the stack in the order:
  1060.  
  1061.          #pop end1 radius1 end2 radius2
  1062.  
  1063.   If you are going to put these values from the stack directly into a
  1064.   raytracer cone statement, then you could use them directly from the
  1065.   stack by doing:
  1066.  
  1067.           cone { %()%, %()%, %()%, %()% }
  1068.  
  1069.   Reading from left to right, the first "()" would pop end1 off of the
  1070.   stack, the second "()" would pop radius1 off of the stack, the third
  1071.   "()" would pop end2 off of the stack, and the last "()" would pop
  1072.   radius2 off of the stack.  This format is consistent with the POV and
  1073.   Polyray cone statements.
  1074.  
  1075.  
  1076.   The #read command:
  1077.  
  1078.     The #read command will read one line of values out of an input file
  1079.   that you have opened, and leave them on the stack, along with a count
  1080.   of how many values that were found.  This comes in handy for reading
  1081.   in a file of raw numeric data such as raw triangle files (although it
  1082.   will not perform any "smoothing" on raw triangle data).  The #read
  1083.   command only reads one line at a time.  The numbers on this line may
  1084.   be separated by spaces and/or commas.  The numbers are pushed onto
  1085.   the stack as they are read in from left to right, and when this is
  1086.   done, a count of how many numbers were found is left on top of the
  1087.   stack.  This count will report 0 (zero) if the line was left blank.
  1088.   This count will also report -1 when the end of the input file has been
  1089.   reached.  The file should contain numbers only,  text will be
  1090.   interpreted as variable names and may cause a "variable not found"
  1091.   error.  The syntax is:
  1092.  
  1093.          #read variable
  1094.          where "variable" contains the file number of a file
  1095.          that you have opened for input
  1096.  
  1097.          Example:
  1098.                  #var infile
  1099.                  #open in infile numbers.inp
  1100.                  #read infile
  1101.  
  1102.   The example read one line of data from the file named "numbers.inp".
  1103.   Suppose numbers.inp contained:
  1104.  
  1105.          11, 12, 13, 14, 15
  1106.  
  1107.   Then, after the #read command the stack would contain:
  1108.  
  1109.         11 12 13 14 15 5
  1110.                        ^Top of stack
  1111.  
  1112.   The number on top of the stack indicates that the #read command found
  1113.   five numbers on the line it read from the "numbers.inp" file.
  1114.   Notice that they must be popped off of the top of stack in the reverse
  1115.   order of the way they were read in.  This is what is meant by the term
  1116.   "last-in-first-out" stack.
  1117.  
  1118.  
  1119.   Axis commands:
  1120.  
  1121.     Axis commands affect an object I call a local axis.  This is not to
  1122.   be confused with the world axis which consists of the origin {0, 0, 0}
  1123.   and the left handed coordinate system that has x, y, and z directions,
  1124.   much the same as POVray and Polyray.  Think of a local axis as a man
  1125.   out in space.  No matter what kind of crazy orientation we on earth
  1126.   see him in, he has his own frame of reference that defines up, down,
  1127.   right, left, forward, and back for him.  The local axis starts out at
  1128.   the origin {0, 0, 0} with it's own x, y and z vectors pointing along
  1129.   the world's x, y, and z directions.  From there we can tell it to turn
  1130.   about it's own center and point it's x, y, and z vectors in different
  1131.   directions.  Then we can tell it to move in a direction relative to
  1132.   it's own x, y, and z vectors.  Once we have done several steps like
  1133.   this, we can then find where the local axis ended up relative to
  1134.   the origin {0, 0, 0} in the world's x, y, and z coordinates.  It's kind
  1135.   of like a remote control airplane that you can tell to pitch up and
  1136.   down (rotate about it's own x vector), yaw right and left (rotate about
  1137.   it's own y vector), and roll right or left (rotate about it's own z
  1138.   vector).  Then you can tell it to move so far left or right (along it's
  1139.   own x vector), so far up or down (along it's own y vector), and so far
  1140.   forward or back (along it's own z vector).  When you are done, you can
  1141.   find the absolute location in world coordinates of your remote control
  1142.   airplane and place a raytracer object there (like skywriting).
  1143.   L. J. Lapre's LPARSER uses commands like this to move a "turtle" (I
  1144.   have yet to see a flying turtle), and do L-system objects like trees
  1145.   and plants.  With axis commands and recursive subprograms, I have been
  1146.   able to do the same kind of L-system objects and output them directly
  1147.   to raytracer format.
  1148.  
  1149.   The #axis move command:
  1150.  
  1151.     This command serves to move the local axis object along it's own x,
  1152.   y, and z vectors.  Remember the remote control airplane?  Well, the
  1153.   +x vector would point along the right wing, the +y vector would point
  1154.   out of the top of the airplane, and the +z vector would point out of
  1155.   the front of the airplane.  The syntax is:
  1156.  
  1157.          #axis move vector_value
  1158.  
  1159.          Example:
  1160.                  #axis move {3, 4, 5}
  1161.  
  1162.   The example would move the remote control airplane 3 units along the
  1163.   direction of it's right wing, 4 units along the direction pointing out
  1164.   of the top of the airplane and 5 units towards the front of the
  1165.   airplane.
  1166.  
  1167.   The #axis move command is also an RPN function:
  1168.  
  1169.                           Value          Axis
  1170.          Function:        Stack:         Stack:
  1171.  
  1172.               move        (n1 ->  )      (  ->  )
  1173.  
  1174.   So the command:
  1175.  
  1176.          #eval {3, 4, 5} move
  1177.  
  1178.   Would perform the same move as the example using the #axis move command.
  1179.  
  1180.  
  1181.   The #axis pitch command:
  1182.  
  1183.     The axis turn command turns the local axis about it's own x vector in
  1184.   order to point it's y, and z vectors in new directions.  Pitch is when
  1185.   you move the nose of the airplane up, or down by rotating about the axis
  1186.   formed by your wings (in this case rotating about our +x vector pointing
  1187.   along the right wing).  Note that this has the effect of changing the
  1188.   orientation of your airplane and pointing the y and z vectors in new
  1189.   directions.  The syntax is:
  1190.  
  1191.          #axis pitch angle_value
  1192.  
  1193.          Example:
  1194.                  #axis pitch 30
  1195.  
  1196.   The example would Pitch the nose of the airplane down by 30 degrees
  1197.   (rotating about the +x vector in a left hand coordinate system).
  1198.  
  1199.   The #axis pitch command is also an RPN function:
  1200.  
  1201.                           Value         Axis
  1202.          Function:        Stack:        Stack:
  1203.  
  1204.              pitch        (n1 ->  )     (  ->  )
  1205.  
  1206.   So the command:
  1207.  
  1208.          #eval 30 pitch
  1209.  
  1210.   Would do same function as the example using the #axis pitch command.
  1211.  
  1212.  
  1213.   The #axis yaw command:
  1214.  
  1215.     The axis yaw command turns the local axis about it's own y vector in
  1216.   order to point it's x, and z vectors in new directions.  Yaw is when you
  1217.   move the nose of the airplane left or right by rotating about the axis
  1218.   formed by the top an bottom of the airplane (in this case rotating about
  1219.   the +y vector pointing out the top of our airplane).  This will change
  1220.   the airplane's orientation and will point the x, and z vectors in new
  1221.   directions.  The syntax is:
  1222.  
  1223.          #axis yaw angle_value
  1224.  
  1225.          Example:
  1226.                  #axis yaw 60
  1227.  
  1228.   The example would Yaw the nose of the airplane right by 60 degrees
  1229.   (rotating about the +y vector in a left hand coordinate system).
  1230.  
  1231.   The #axis yaw command is also an RPN function:
  1232.  
  1233.                           Value         Axis
  1234.          Function:        Stack:        Stack:
  1235.  
  1236.                yaw        (n1 ->  )     (  ->  )
  1237.  
  1238.   So the command:
  1239.  
  1240.          #eval 60 yaw
  1241.  
  1242.   Would do the same function as the example using the #axis yaw command.
  1243.  
  1244.  
  1245.   The #axis roll command:
  1246.  
  1247.     The #axis roll command rolls the local axis about it's own z vector
  1248.   in order to point it's x and y vectors in new directions.  Roll is when
  1249.   you roll the airplane over by rotating about the axis formed by the nose
  1250.   and tail of the airplane (in this case rotating about the +z vector
  1251.   pointing out of the nose of the airplane).  This points the airplanes x,
  1252.   and y vectors in new directions.  The syntax is:
  1253.  
  1254.          #axis roll angle_value
  1255.  
  1256.          Example:
  1257.                  #axis roll 90
  1258.  
  1259.   The example would Roll the airplane left by 90 degrees (rotating
  1260.   about the +z vector in a left handed coordinate system).
  1261.  
  1262.   The #axis roll command is also an RPN function:
  1263.  
  1264.                           Value         Axis
  1265.          Function:        Stack:        Stack:
  1266.  
  1267.               roll        (n1 ->  )     (  ->  )
  1268.  
  1269.   So the command:
  1270.  
  1271.          #eval 90 roll
  1272.  
  1273.   Would do the same function as the example using the #axis roll command.
  1274.  
  1275.  
  1276.   The #axis rotate command:
  1277.  
  1278.     The #axis rotate command rotates the local axis about it's center
  1279.   relative to the worlds x, y, and z directions.   This will be a left
  1280.   handed rotation.  That is, point your left thumb in the direction of the
  1281.   vector you wish to turn the airplane about, and your fingers curl in the
  1282.   direction of the turn.  Think of the airplane as a raytracer object in
  1283.   POV or Polyray and you are changing it's orientation with the "rotate"
  1284.   object modifier.  The syntax is:
  1285.  
  1286.          #axis rotate vector_value
  1287.  
  1288.          Example:
  1289.                  #axis rotate {10, 20, 30}
  1290.  
  1291.   The example would rotate the airplane about it's center by 10 degrees
  1292.   about the world's x direction, then by 20 degrees about the world's y
  1293.   direction, and then by 30 degrees about the world's z direction.
  1294.  
  1295.   The #axis rotate command is also an RPN function:
  1296.  
  1297.                           Value         Axis
  1298.          Function:        Stack:        Stack:
  1299.  
  1300.               arot        (n1 ->  )     (  ->  )
  1301.  
  1302.   So the command:
  1303.  
  1304.          #eval {30, 60, 90} arot
  1305.  
  1306.   Would perform the same as the example using the #axis rotate command.
  1307.  
  1308.  
  1309.   The #axis turn command:
  1310.  
  1311.     The axis turn command turns the local axis about an arbitrary absolute
  1312.   vector in order to point it's x, y, and z vectors in new directions.
  1313.   To the remote control airplane, this would be equivalent to you reaching
  1314.   out and turning the airplane about an axis of your choosing.  This
  1315.   will be a left handed rotation.  That is, point your left thumb in the
  1316.   direction of the vector you wish to turn the airplane about, and your
  1317.   fingers curl in the direction of the turn.  The airplanes location is
  1318.   not changed, but the x, y, and z vectors will point in different
  1319.   directions.  The syntax is:
  1320.  
  1321.          #axis turn vector_value angle_value
  1322.  
  1323.          Example:
  1324.                  #axis turn {1, 1, 1} 45
  1325.  
  1326.   The example would turn the airplane about the vector {1, 1, 1} by 45
  1327.   degrees.  Imagine connecting an end of a stick that points in the absolute
  1328.   direction {1, 1, 1} to your remote control airplane and then rolling
  1329.   that stick between your fingers so that the airplane connected to the
  1330.   end turns 45 degrees about the axis of the stick.
  1331.  
  1332.   The #axis turn command is also an RPN function:
  1333.  
  1334.                           Value         Axis
  1335.          Function:        Stack:        Stack:
  1336.  
  1337.              aturn        (n1 n2 ->  )  (  ->  )
  1338.  
  1339.   So the command:
  1340.  
  1341.          #eval {1, 1, 1} 45 aturn
  1342.  
  1343.   Would perform the same function as the example using the #axis turn command.
  1344.  
  1345.  
  1346.     The #axis location? command:
  1347.  
  1348.     The #axis location? command will get the current location of the
  1349.   local axis in absolute world coordinates.  In other words, after you
  1350.   have told the remote control airplane to to pitch, yaw, roll, and move
  1351.   several times, this command will report the location of the airplane
  1352.   relative to the origin {0, 0, 0} and the world's x, y, z directions.
  1353.   The syntax is:
  1354.  
  1355.          #axis location? variable
  1356.  
  1357.          Example:
  1358.                  #axis location? a
  1359.  
  1360.   The example would get the current location (as a vector) of the remote
  1361.   control airplane and assign it to variable "a".  As I said, you could
  1362.   then have a raytracer statement put an object at this location and the
  1363.   effect would be as if you flew your remote control airplane to a
  1364.   certain point in the air and had it hang a raytracer object there.
  1365.  
  1366.   The #axis location? command is also an RPN function:
  1367.  
  1368.                           Value        Axis
  1369.          Function:        Stack:       Stack:
  1370.  
  1371.               loc?        (  -> n1)    (  ->  )
  1372.  
  1373.   So the command:
  1374.  
  1375.          #eval a loc? ==
  1376.  
  1377.   Would get the same answer as the example using the #axis location? command.
  1378.  
  1379.  
  1380.   The #axis push command:
  1381.  
  1382.     The #axis push command will take the local axis location and
  1383.   orientation and push them on to a "last in first out" stack.  This is
  1384.   like taking a snapshot of the remote control airplane's location and
  1385.   orientation and putting it in top of a pile so that you can look at it
  1386.   later and put the airplane back the way it was when the snapshot was
  1387.   taken.  The syntax is:
  1388.  
  1389.          #axis push
  1390.  
  1391.   The #axis push command is also an RPN function:
  1392.  
  1393.                           Value          Axis
  1394.          Function:        Stack:         Stack:
  1395.  
  1396.               apush       (  ->  )       ( -> ax1)
  1397.  
  1398.   So the command:
  1399.  
  1400.          #eval apush
  1401.  
  1402.   Would perform the same function as the example using the #axis push command.
  1403.  
  1404.  
  1405.   The #axis pop command:
  1406.  
  1407.     The #axis pop command will set the local axis location and
  1408.   orientation to be the same as values it pops off of the top of a "last
  1409.   in first out" stack.  This is like picking up a snapshot of the remote
  1410.   control airplane's location and orientation off of the top of a pile
  1411.   and using it to put the airplane back the way it was when the snapshot
  1412.   was taken.  The syntax is:
  1413.  
  1414.          #axis pop
  1415.  
  1416.   The #axis pop command is also an RPN function:
  1417.  
  1418.                           Value         Axis
  1419.          Function:        Stack:        Stack:
  1420.  
  1421.               apop        (  ->  )      (ax1 ->  )
  1422.  
  1423.   So the command:
  1424.  
  1425.          #eval apop
  1426.  
  1427.   Would perform the same function as the example using the #axis pop command.
  1428.  
  1429.  
  1430.   The #axis dupe command:
  1431.  
  1432.     The #axis dupe command will make a copy of the local axis location and
  1433.   orientation it finds on top of the "last in first out" stack and will put
  1434.   the copy on top of the stack.  This is like making a copy of a snapshot
  1435.   of the remote control airplane's location and orientation from the snapshot
  1436.   on top of the pile and then putting the copy on top of the pile.
  1437.   The syntax is:
  1438.  
  1439.          #axis dupe
  1440.  
  1441.   The #axis dupe command is also an RPN function:
  1442.  
  1443.                           Value         Axis
  1444.          Function:        Stack:        Stack:
  1445.  
  1446.               adupe        (  ->  )      (ax1 -> ax1 ax1)
  1447.  
  1448.   So the command:
  1449.  
  1450.          #eval adupe
  1451.  
  1452.   Would perform the same function as the example using the #axis dupe command.
  1453.  
  1454.  
  1455.   The #axis swap command:
  1456.  
  1457.     The #axis swap command will swap the top 2 copies of the local axis
  1458.   location and orientation it finds on top of the "last in first out"
  1459.   stack.  This is like swapping the top 2 snapshots of the remote control
  1460.   airplane's location and orientation that are on top of the pile.
  1461.   The syntax is:
  1462.  
  1463.          #axis swap
  1464.  
  1465.   The #axis swap command is also an RPN function:
  1466.  
  1467.                           Value         Axis
  1468.          Function:        Stack:        Stack:
  1469.  
  1470.               aswap       (  ->  )      (ax1 ax2 -> ax2 ax1)
  1471.  
  1472.   So the command:
  1473.  
  1474.          #eval aswap
  1475.  
  1476.   Would perform the same function as the example using the #axis swap command.
  1477.  
  1478.  
  1479.   The #axis drop command:
  1480.  
  1481.     The #axis drop command will destroy the top copy of the local axis
  1482.   location and orientation it finds on top of the "last in first out"
  1483.   stack.  This is like tossing out the top snapshot of the remote control
  1484.   airplane's location and orientation that was on top of the pile.
  1485.   The syntax is:
  1486.  
  1487.          #axis drop
  1488.  
  1489.   The #axis swap command is also an RPN function:
  1490.  
  1491.                           Value         Axis
  1492.          Function:        Stack:        Stack:
  1493.  
  1494.               adrop       (  ->  )      (ax1 ->  )
  1495.  
  1496.   So the command:
  1497.  
  1498.          #eval adrop
  1499.  
  1500.   Would perform the same function as the example using the #axis drop command.
  1501.  
  1502.  
  1503.   The #axis drag command:
  1504.  
  1505.     The #axis drag command will take the local axis object and drag it
  1506.   in a specified direction relative to the world's x, y, and z
  1507.   directions.  The effect is as if you had whipped up a gust of wind and
  1508.   dragged the remote control airplane from it's current location by a
  1509.   certain amount and didn't change the airplane's orientation at all.
  1510.   The syntax is:
  1511.  
  1512.          #axis drag vector_value
  1513.  
  1514.          Example:
  1515.                  #axis drag {3, 4, 5}
  1516.  
  1517.   The example would take the airplane and drag it 3 units in the
  1518.   world's x direction, 4 units in the world's y direction, and 5 units
  1519.   in the world's z direction.
  1520.  
  1521.   The #axis drag command is also an RPN function:
  1522.  
  1523.                           Value        Axis
  1524.          Function:        Stack:       Stack:
  1525.  
  1526.               drag        (n1  ->  )   (  ->  )
  1527.  
  1528.   So the command:
  1529.  
  1530.          #eval {3, 4, 5} drag
  1531.  
  1532.   Would perform the same function as the example using the #axis drag command.
  1533.  
  1534.  
  1535.   The #axis place command:
  1536.  
  1537.     The #axis place command takes the local axis object and places it at
  1538.   an x, y, and z world coordinate relative to the origin.  The effect
  1539.   is as if you suddenly teleported the remote control airplane from
  1540.   wherever it is to a certian point in the air specified by world x, y,
  1541.   and z coordinates.  The airplane's orientation will not be changed at
  1542.   all.  The syntax is:
  1543.  
  1544.          #axis place vector_value
  1545.  
  1546.          Example:
  1547.                  #axis place {0, 0, 0}
  1548.  
  1549.   The example will get the airplane from wherever it is and place it at
  1550.   the origin.  It will now report a location of <0, 0, 0>.
  1551.  
  1552.   The #axis place command is also an RPN function:
  1553.  
  1554.                           Value        Axis
  1555.          Function:        Stack:       Stack:
  1556.  
  1557.              place        (n1  ->  )   (  ->  )
  1558.  
  1559.   So the command:
  1560.  
  1561.          #eval {0, 0, 0} place
  1562.  
  1563.   Would perform the same move as the example using the #axis place command.
  1564.  
  1565.  
  1566.   The #axis orient command:
  1567.  
  1568.     The axis orient command will rotate the local axis object so that
  1569.   it's x, y, and z vectors point along the world's x, y and z directions.
  1570.   The effect is as if you took the remote control airplane, put it straight
  1571.   and level.  The airplane's location does not change.
  1572.   The syntax is:
  1573.  
  1574.          #axis orient
  1575.  
  1576.          Example:
  1577.                  #axis orient
  1578.  
  1579.   The example would flop the airplane over and turn it so that it's
  1580.   right wing (+x vector) pointed towards the world's +x direction, and
  1581.   the top of the airplane (+y vector) pointed in the world's +y
  1582.   direction, and the nose of the airplane (+z vector) points toward the
  1583.   world's +z direction.
  1584.  
  1585.   The #axis orient command is also an RPN function:
  1586.  
  1587.                           Value        Axis
  1588.          Function:        Stack:       Stack:
  1589.  
  1590.             orient        (  ->  )     (  ->  )
  1591.  
  1592.   So the command:
  1593.  
  1594.          #eval orient
  1595.  
  1596.   Would perform the same move as the example using the #axis orient command.
  1597.  
  1598.  
  1599.   The #axis rotation? command:
  1600.  
  1601.     The #axis rotation? command will report the current orientation of
  1602.   the local axis object relative to rotation about the world's x, y,
  1603.   and z directions.  Think of it as asking "If I had another airplane,
  1604.   sitting straight and level, How much would I have to rotate it about
  1605.   the world's x, y, and z directions in order to put it in the same
  1606.   orientation as the current airplane?".
  1607.   The syntax is:
  1608.  
  1609.          #axis rotation? variable
  1610.  
  1611.          Example:
  1612.                  #axis rotation? a
  1613.  
  1614.   The example would find the current orientation of the local axis and put
  1615.   it (as a vector) in the variable "a".  This can be useful if you have
  1616.   a raytracer object that you want to rotate so that it aligns with the
  1617.   local axis.  You might even define a raytraced airplane object and put
  1618.   it in the same orientation as the local axis, which I compare to a
  1619.   remote control airplane so much.
  1620.  
  1621.   The #axis rotation? command is also an RPN function:
  1622.  
  1623.                           Value        Axis
  1624.          Function:        Stack:       Stack:
  1625.  
  1626.               rot?        (  ->  n1)   (  ->  )
  1627.  
  1628.   So the command:
  1629.  
  1630.          #eval a rot? ==
  1631.  
  1632.   Would find the same value as the example using the #axis rotation? command.
  1633.  
  1634.  
  1635.   The #axis roll? command:
  1636.  
  1637.     The #axis roll? command will will report the roll angle of the local
  1638.   axis object.  This is like finding out how far the airplane has rolled
  1639.   about it's +z vector from "wings level" (the +x vector being level
  1640.   with the "ground" and the +y vector pointing skyward).
  1641.   The syntax is:
  1642.  
  1643.          #axis roll? variable
  1644.  
  1645.          Example:
  1646.                  #axis roll? a
  1647.  
  1648.   The example would find out how far the airplane has rolled from "wings
  1649.   level", and put it as a number in variable "a".  To make the airplane
  1650.   level it's wings we could use the command "#axis turn {0, 0, -a}".
  1651.   We must roll by -a because the airplane is already at the roll angle
  1652.   in variable "a" and we must set it back to zero.
  1653.  
  1654.   The #axis roll? command is also an RPN function:
  1655.  
  1656.                           Value        Axis
  1657.          Function:        Stack:       Stack:
  1658.  
  1659.               roll?       (  -> n1)    (  ->  )
  1660.  
  1661.   So the command:
  1662.  
  1663.          #eval a roll? ==
  1664.  
  1665.   Would find the same value as the example using the #axis roll? command.
  1666.  
  1667.  
  1668.   The #axis yaw? command:
  1669.  
  1670.     The #axis yaw? command will report the yaw angle of the local axis
  1671.   object.  This is like finding out how far the airplane has rotated
  1672.   about it's +y vector from having it's nose pointed only in the world's
  1673.   y and z directions and it's right hand wing on the world's +x side of
  1674.   the airplane.
  1675.   The syntax is:
  1676.  
  1677.          #axis yaw? variable
  1678.  
  1679.          Example:
  1680.                  #axis yaw? a
  1681.  
  1682.   The #axis yaw? command is also an RPN function:
  1683.  
  1684.                           Value        Axis
  1685.          Function:        Stack:       Stack:
  1686.  
  1687.               yaw?        (  -> n1)    (  ->  )
  1688.  
  1689.   So the command:
  1690.  
  1691.          #eval a yaw? ==
  1692.  
  1693.   Would find the same value as the example using the #axis yaw? command.
  1694.  
  1695.  
  1696.   The #axis pitch? command:
  1697.  
  1698.     The #axis pitch? command will report the pitch angle of the local
  1699.   axis object.  This is like finding out how far the airplane has
  1700.   rotated about it's wings (the +x vector) from having it's nose level
  1701.   with the ground and it's +y vector pointing skyward.
  1702.   The syntax is:
  1703.  
  1704.          #axis pitch? variable
  1705.  
  1706.          Example:
  1707.                  #axis pitch? a
  1708.  
  1709.   The #axis pitch? command is also an RPN function:
  1710.  
  1711.                           Value        Axis
  1712.          Function:        Stack:       Stack:
  1713.  
  1714.             pitch?        (  -> n1)    (  ->  )
  1715.  
  1716.   So the command:
  1717.  
  1718.          #eval a pitch? ==
  1719.  
  1720.   Would find the same value as the example using the #axis pitch? command.
  1721.  
  1722.  
  1723.   The #axis swing command:
  1724.  
  1725.     The #axis rotate command will take the local axis object and rotate
  1726.   it about the origin and the world's x, y, and z directions.  This is
  1727.   like standing at the origin and throwing a lasso around your remote
  1728.   control airplane, and then swinging the airplane around the origin
  1729.   relative to the worlds x, y, and z directions.  The syntax is:
  1730.  
  1731.          #axis swing vector_value
  1732.  
  1733.          Example:
  1734.                  #axis swing {30, 40, 50}
  1735.  
  1736.   The example will take the airplane and rotate it about the world's x,
  1737.   y, and z directions by 30, 40, and 50 degrees respectively.  If the
  1738.   airplane was not at located at the origin, then it's location would be
  1739.   rotated about the origin as well as having it's orientation rotated.
  1740.  
  1741.   The #axis swing command is also an RPN function:
  1742.  
  1743.                           Value        Axis
  1744.          Function:        Stack:       Stack:
  1745.  
  1746.               swing       (n1 ->   )   (  ->  )
  1747.  
  1748.   So the command:
  1749.  
  1750.          #eval {30, 40, 50} swing
  1751.  
  1752.   Would perform the same move as the example using the #axis swing command.
  1753.  
  1754.  
  1755.   The #axis sweep commmand:
  1756.  
  1757.     The #axis sweep command will sweep the local axis around an arbitrary
  1758.   vector.  This is like going out to a point in space, throwing a lasso
  1759.   around the remote control airplane, and swinging the airplane around an
  1760.   axis of your choosing.  This will be a left handed rotation.  That is,
  1761.   point your left thumb in the direction of the vector you intend to sweep
  1762.   the local axis about and your fingers will point in the direction of the
  1763.   rotation.  The syntax is:
  1764.  
  1765.          #axis sweep axis_vector angle_value
  1766.  
  1767.          Example:
  1768.                  #axis sweep {1, 1, 1} 45
  1769.  
  1770.   The Example would be like you starting at the origin, moving along the
  1771.   vector {1, 1, 1} to the point on that vector closest to the airplane, and
  1772.   then throwing your lasso around the airplane and swinging the airplane
  1773.   around the vector {1, 1, 1} by 45 degrees.  The airplane's location will
  1774.   be rotated around the vector as well as the orientation.
  1775.  
  1776.   The #axis sweep command is also an RPN function:
  1777.  
  1778.                           Value        Axis
  1779.          Function:        Stack:       Stack:
  1780.  
  1781.              sweep        (n1 n2 -> )  (  ->  )
  1782.  
  1783.   So the command:
  1784.  
  1785.          #eval {1, 1, 1} 45 sweep
  1786.  
  1787.   Would perform the same move as the example using the #axis sweep command.
  1788.  
  1789.  
  1790.   The #axis bend command:
  1791.  
  1792.     The #axis bend command is used to adjust the orientation of the
  1793.   local axis object in order to simulate bending due to gravity as the
  1794.   local axis moves from point to point.  This is like when the remote
  1795.   control airplane moves in a certain direction, but gravity in the
  1796.   axis "down" direction pulls on it so that it ends up a little lower then
  1797.   it would have been if there were no gravity.  The axis "down"
  1798.   direction defaults to the -y world direction, but may be changed by
  1799.   the #axis down command (see below).  You specify the direction
  1800.   that you intend to move in, and the amount of gravity in the axis down
  1801.   direction, and the command will change the orientation of the airplane
  1802.   so that a move in that direction (relative to the airplane's x, y, and z
  1803.   vectors) will end up a little lower in world coordinates then it would
  1804.   have been with no gravity.  The syntax is:
  1805.  
  1806.          #axis bend vector_value gravity_value
  1807.  
  1808.          Example:
  1809.                  #axis bend {0, 0, 10} 0.2
  1810.                  #axis move {0, 0, 10}
  1811.  
  1812.   In the example, assuming we started out straight and level at the
  1813.   origin, instead of ending up at the location {0, 0, 10}, gravity would
  1814.   pull down on this move in the -y world direction so that the airplane
  1815.   would end up at approximate location {0, -2, 9.8}.  The #axis bend
  1816.   command has actually pitched the nose of the airplane down a little so
  1817.   that a move of {0, 0, 10} ends up at location {0, -2, 9.5}.  Note that
  1818.   gravity would have no effect if we were trying to move straight up (+y
  1819.   world direction) or straight down (-y world direction), the same way
  1820.   that gravity would not bend a tree branch pointing straight up or
  1821.   straight down.  The tree branch that gravity would bend the most is
  1822.   one hanging out over the ground.  Funny I should mention tree branches
  1823.   because this command can be used to simulate the "tropism" (bending of
  1824.   plant branches due to gravity) command used in the L-systems included
  1825.   with L. J. Lapre's LPARSER.  Some example files of trees taken from
  1826.   LPARSER (which LPARSER has taken from the Book "The Algorithmic Beauty
  1827.   of Plants"), are included along with this package.
  1828.  
  1829.   The #axis bend command is also an RPN function:
  1830.  
  1831.                           Value        Axis
  1832.          Function:        Stack:       Stack:
  1833.  
  1834.               bend       (n1 n2 ->  )  (  ->  )
  1835.  
  1836.   So the command:
  1837.  
  1838.          #eval {0, 0, 10} dupe 0.2 bend move
  1839.  
  1840.   Would perform the same bend and move as the example using the #axis
  1841.   bend and #axis move commands.
  1842.  
  1843.  
  1844.   The #axis down command:
  1845.  
  1846.     The #axis down command sets the "down" direction for the #axis bend
  1847.   command.  This is like setting which way that gravity pulls on the
  1848.   remote control airplane.  The syntax is:
  1849.  
  1850.          #axis down vector_value
  1851.  
  1852.          Example:
  1853.                  #axis down {1, 0, 0}
  1854.                  #axis bend {0, 0, 10} 0.2
  1855.                  #axis move {0, 0, 10}
  1856.  
  1857.   The example sets the down direction to be in the +x world direction
  1858.   and then performs a bend and move in the {0, 0, 10} direction.  The
  1859.   net effect is that gravity now pulls on this move in the +x world
  1860.   direction so that this move would put the axis at {2, 0, 9.8} in
  1861.   absolute world coordinates instead of {0, 0, 10} if there were no
  1862.   bend.
  1863.  
  1864.   The #axis down command is also an RPN function:
  1865.  
  1866.                           Value        Axis
  1867.          Function:        Stack:       Stack:
  1868.  
  1869.              adown       (n1  ->  )    (  ->  )
  1870.  
  1871.   So the command:
  1872.  
  1873.          #eval {1, 0, 0} adown {0, 0, 10} dupe 0.2 bend move
  1874.  
  1875.   Would perform the same bend and move as the example using the #axis
  1876.   down, #axis bend and #axis move commands.
  1877.  
  1878.  
  1879.   The #axis relcoord? command
  1880.  
  1881.     The axis relcoord? command will take a coordinate in absolute x, y,
  1882.   and z directions from the origin and find the relative coordinate
  1883.   along the local axis x, y, and z vectors from the center of the local
  1884.   axis.  That is like asking the remote control airplane how far away
  1885.   a certain point in space is from the airplane.
  1886.   The syntax is:
  1887.  
  1888.          #axis relcoord? variable vector_value
  1889.  
  1890.          Example:
  1891.                  #axis relcoord? a {10, 10, 10}
  1892.  
  1893.   The Example will set "a" equal to a vector value that represents the
  1894.   distance along the airplanes x, y, and z vectors that the absolute
  1895.   point {10, 10, 10} is away from the airplane.
  1896.  
  1897.   The #axis relcoord? command is also an RPN function:
  1898.  
  1899.                           Value        Axis
  1900.          Function:        Stack:       Stack:
  1901.  
  1902.          relcoord?        (n1 -> n2)   (  ->  )
  1903.  
  1904.   So the command:
  1905.  
  1906.          #eval a {10, 10, 10} relcoord? ==
  1907.  
  1908.   Would perform the same function as the example using the #axis relcoord?
  1909.   command.
  1910.  
  1911.  
  1912.   The #axis abscoord? command
  1913.  
  1914.     The axis abscoord? command will take a coordinate in distances along
  1915.   the local axis x, y, and z vectors from the center of the local axis and
  1916.   find the absolute coordinate along the world x, y, and z directions from
  1917.   the origin.  That is like asking the remote control airplane what the
  1918.   world coordinate is of a point that is a certain distance from it.
  1919.   The syntax is:
  1920.  
  1921.          #axis abscoord? variable vector_value
  1922.  
  1923.          Example:
  1924.                  #axis abscoord? a {10, 10, 10}
  1925.  
  1926.   The Example will set "a" equal to a vector value that represents the
  1927.   distance along the world's x, y, and z directions from the origin of a
  1928.   point that is {10, 10, 10} in distances along the airplanes x, y, and
  1929.   z vectors away from the airplane.
  1930.  
  1931.   The #axis abscoord? command is also an RPN function:
  1932.  
  1933.                           Value        Axis
  1934.          Function:        Stack:       Stack:
  1935.  
  1936.          abscoord?        (n1 -> n2)   (  ->  )
  1937.  
  1938.   So the command:
  1939.  
  1940.          #eval a {10, 10, 10} abscoord? ==
  1941.  
  1942.   Would perform the same function as the example using the #axis abscoord?
  1943.   command.
  1944.  
  1945.  
  1946.   The #axis alignx command:
  1947.  
  1948.     The #axis alignx command is used to aim the local axis x vector at a
  1949.   certain point specified in absolute world coordinates.  This like
  1950.   telling the remote control airplane to point it's right wing at a
  1951.   certain point in space.
  1952.   The syntax is:
  1953.  
  1954.          #axis alignx vector_value
  1955.  
  1956.          Example:
  1957.                  #axis alignx {10, 10, 10}
  1958.  
  1959.   The example would aim the right wing of the airplane at the point
  1960.   {10, 10, 10} (specified in distances along the world's x, y, and z
  1961.   directions from the origin).  The airplane will accomplish by first
  1962.   doing a yaw about it's y vector and then doing a roll about it's z
  1963.   vector.  So the x vector will be aiming at the specified point and the
  1964.   y and z vectors will be pointing in new directions also.
  1965.  
  1966.   The #axis alignx command is also an RPN function:
  1967.  
  1968.                           Value        Axis
  1969.          Function:        Stack:       Stack:
  1970.  
  1971.             alignx        (n1 ->  )    (  ->  )
  1972.  
  1973.   So the command:
  1974.  
  1975.          #eval {10, 10, 10} alignx
  1976.  
  1977.   Would perform the same function as the example using the #axis alignx
  1978.   command.
  1979.  
  1980.  
  1981.   The #axis aligny command:
  1982.  
  1983.     The #axis aligny command is used to aim the local axis y vector at a
  1984.   certain point specified in absolute world coordinates.  This like
  1985.   telling the remote control airplane to point it's top at a certain point
  1986.   in space.
  1987.   The syntax is:
  1988.  
  1989.          #axis aligny vector_value
  1990.  
  1991.          Example:
  1992.                  #axis aligny {10, 10, 10}
  1993.  
  1994.   The example would aim the top of the airplane at the point {10, 10, 10}
  1995.   (specified in distances along the world's x, y, and z directions from
  1996.   the origin).  The airplane will accomplish by first doing a pitch about
  1997.   it's x vector and then doing a roll about it's z vector.  So the y vector
  1998.   will be aiming at the specified point and the x and z vectors will be
  1999.   pointing in new directions also.
  2000.  
  2001.   The #axis aligny command is also an RPN function:
  2002.  
  2003.                           Value        Axis
  2004.          Function:        Stack:       Stack:
  2005.  
  2006.             aligny        (n1 ->  )    (  ->  )
  2007.  
  2008.   So the command:
  2009.  
  2010.          #eval {10, 10, 10} aligny
  2011.  
  2012.   Would perform the same function as the example using the #axis aligny
  2013.   command.
  2014.  
  2015.  
  2016.   The #axis alignz command:
  2017.  
  2018.     The #axis alignz command is used to aim the local axis z vector at a
  2019.   certain point specified in absolute world coordinates.  This like
  2020.   telling the remote control airplane to point it's nose at a certain
  2021.   point in space.
  2022.   The syntax is:
  2023.  
  2024.          #axis alignz vector_value
  2025.  
  2026.          Example:
  2027.                  #axis alignz {10, 10, 10}
  2028.  
  2029.   The example would aim the nose of the airplane at the point {10, 10, 10}
  2030.   (specified in distances along the world's x, y, and z directions from
  2031.   the origin).  The airplane will accomplish by first doing a pitch about
  2032.   it's x vector and then doing a yaw about it's y vector.  So the z vector
  2033.   will be aiming at the specified point and the x and y vectors will be
  2034.   pointing in new directions also.
  2035.  
  2036.   The #axis alignz command is also an RPN function:
  2037.  
  2038.                           Value        Axis
  2039.          Function:        Stack:       Stack:
  2040.  
  2041.             alignz        (n1 ->  )    (  ->  )
  2042.  
  2043.   So the command:
  2044.  
  2045.          #eval {10, 10, 10} alignz
  2046.  
  2047.   Would perform the same function as the example using the #axis alignz
  2048.   command.
  2049.  
  2050.  
  2051.   Tips:
  2052.  
  2053.     LPARSER's "$" command (roll the "turtle" until it is level) is
  2054.   equivalent to the axis commands:
  2055.  
  2056.          #axis roll? r
  2057.          #axis roll -r
  2058.  
  2059.      or the RPN expression:
  2060.  
  2061.          #eval -(roll?) roll
  2062.  
  2063.  
  2064.     Don't try to split subprogram definitions, If blocks, or
  2065.   DO-UNTIL loops between input files.  Meaning don't have the #sub
  2066.   command in one input file and the #endsub command in another, or the
  2067.   #do and #until commands in different files, or the #if, #else, and #endif
  2068.   commands in separate input files.
  2069.  
  2070.  
  2071.     If you define subprograms in a separate input file, do not close
  2072.   that file until you are all done calling those subprograms.
  2073.  
  2074.  
  2075.     Failing to put the #seed command in a program which uses random
  2076.   numbers has the same effect as seeding the random number generator
  2077.   with the same value every time, and you will get the same sequence of
  2078.   random numbers each time.
  2079.  
  2080.  
  2081.   Disclaimer:
  2082.  
  2083.     This program is guaranteed to occupy disk space.
  2084.     This program is guaranteed to be originally written by John R. Wind.
  2085.     Beyond that, you are on your own.
  2086.  
  2087.